home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / libg++ / libio / dbz / dbzmain.c < prev    next >
C/C++ Source or Header  |  1994-02-15  |  11KB  |  519 lines

  1. /*
  2.  * dbz - use and test dbz in various ways
  3.  *
  4.  * -Log-
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <string.h>
  11. #include <dbz.h>
  12.  
  13. #ifdef FUNNYSEEKS
  14. #include <unistd.h>
  15. #else
  16. #define    SEEK_SET    0
  17. #endif
  18.  
  19. #define    STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
  20.  
  21. #ifndef lint
  22. static char RCSid[] = "$Header: /rel/cvsfiles/devo/libio/dbz/dbzmain.c,v 1.2 1993/10/25 20:02:41 bothner Exp $";
  23. #endif
  24.  
  25. char *progname;
  26.  
  27. char *inname = "(no file)";        /* filename for messages etc. */
  28. long lineno;                /* line number for messages etc. */
  29.  
  30. char *basename;
  31. char *pagname;
  32. char *dirname;
  33. char *str2dup();
  34. FILE *base;
  35.  
  36. int op = 'b';            /* what to do, default build a new table */
  37. int baseinput = 1;        /* is the base file also the input? */
  38.  
  39. char *from = NULL;        /* old table to use for dbzagain() */
  40. int omitzero = 0;        /* omit lines tagged with 0 */
  41. long every = 0;            /* report every n lines */
  42. int syncs = 0;            /* dbzsync() on each report */
  43. int quick = 0;            /* quick checking, not too thorough */
  44. int sweep = 0;            /* sweep file checking all offsets */
  45. int useincore = 1;        /* should we use incore facility? */
  46. long xxx = 0;            /* debugging variable */
  47. int printx = 0;            /* print xxx after all is done */
  48. int unique = 1;            /* before store(), check with fetch() */
  49. int usefresh = 0;        /* use dbzfresh? */
  50. long siz = 0;            /* -p size */
  51. char map = 'C';            /* -p map */
  52. long tag = 0;            /* -p tag mask */
  53. int exact = 0;            /* do not run dbzsize(siz) */
  54. int dbzint = 1;            /* use new interface? */
  55. char fs = '\t';            /* field separator, default tab */
  56. int unopen = 0;            /* make base unopenable during dbminit? */
  57. char *change = NULL;        /* chdir here before dbmclose */
  58.  
  59. #define    DEFBUF    1024        /* default line-buffer size */
  60. int buflen = DEFBUF;        /* line length limit */
  61. char lbuf[DEFBUF];
  62. char *line = lbuf;
  63. char cbuf[DEFBUF];
  64. char *cmp = cbuf;
  65.  
  66. void fail();
  67. void dofile();
  68. void runs();
  69. void dosweep();
  70. void mkfiles();
  71. void crfile();
  72. void doline();
  73. void process();
  74.  
  75. #ifdef HAVERFCIZE
  76. extern char *rfc822ize();
  77. #else
  78. #define    rfc822ize(n)    (n)
  79. #endif
  80.  
  81. extern char *malloc();
  82.  
  83. /*
  84.  - main - parse arguments and handle options
  85.  */
  86. main(argc, argv)
  87. int argc;
  88. char *argv[];
  89. {
  90.     int c;
  91.     int errflg = 0;
  92.     extern int optind;
  93.     extern char *optarg;
  94.     int doruns = 0;
  95.     extern long atol();
  96.  
  97.     progname = argv[0];
  98.  
  99.     while ((c = getopt(argc, argv, "axcmt:l:R0E:SqOiX:Yuf:p:eMUC:d")) != EOF)
  100.         switch (c) {
  101.         case 'a':    /* append to existing table */
  102.             if (op != 'b')
  103.                 fail("only one of -a -x -c -m can be given", "");
  104.             op = 'a';
  105.             baseinput = 0;
  106.             break;
  107.         case 'x':    /* extract from existing table */
  108.             if (op != 'b')
  109.                 fail("only one of -a -x -c -m can be given", "");
  110.             op = 'x';
  111.             baseinput = 0;
  112.             break;
  113.         case 'c':    /* check existing table */
  114.             if (op != 'b')
  115.                 fail("only one of -a -x -c -m can be given", "");
  116.             op = 'c';
  117.             break;
  118.         case 'm':    /* extract missing (complement of -x) */
  119.             if (op != 'b')
  120.                 fail("only one of -a -x -c -m can be given", "");
  121.             op = 'm';
  122.             baseinput = 0;
  123.             break;
  124.         case 't':    /* set field separator */
  125.             if (strlen(optarg) > 1)
  126.                 fail("only one field separator allowed", "");
  127.             fs = *optarg;
  128.             break;
  129.         case 'l':    /* override line-length limit */
  130.             buflen = atoi(optarg) + 1;
  131.             if (buflen <= 2)
  132.                 fail("bad -l value `%s'", optarg);
  133.             line = malloc(buflen);
  134.             cmp = malloc(buflen);
  135.             if (line == NULL || cmp == NULL)
  136.                 fail("cannot allocate %s-byte buffers", optarg);
  137.             break;
  138.         case 'R':    /* print run statistics */
  139.             doruns = 1;
  140.             break;
  141.         case '0':    /* omit lines tagged (by fake -t) with 0 */
  142.             omitzero = 1;
  143.             break;
  144.         case 'E':    /* report every n items */
  145.             every = atol(optarg);
  146.             break;
  147.         case 'S':    /* dbzsync() on each -E report */
  148.             syncs = 1;
  149.             break;
  150.         case 'q':    /* quick check or extract */
  151.             quick = 1;
  152.             break;
  153.         case 'O':    /* sweep file checking all offsets */
  154.             sweep = 1;
  155.             break;
  156.         case 'i':    /* don't use incore */
  157.             useincore = 0;
  158.             break;
  159.         case 'X':    /* set xxx */
  160.             xxx = atoi(optarg);
  161.             break;
  162.         case 'Y':    /* print xxx afterward */
  163.             printx = 1;
  164.             break;
  165.         case 'u':    /* don't check uniqueness */
  166.             unique = 0;
  167.             break;
  168.         case 'f':    /* init from existing table's parameters */
  169.             from = optarg;
  170.             break;
  171.         case 'p':    /* parameters for dbzfresh */
  172.             if (sscanf(optarg, "%ld %1s %lx", &siz, &map, &tag) != 3) {
  173.                 map = '?';
  174.                 tag = 0;
  175.                 if (sscanf(optarg, "%ld", &siz) != 1)
  176.                     fail("bad -n value `%s'", optarg);
  177.             }
  178.             usefresh = 1;
  179.             break;
  180.         case 'e':    /* -p size is exact, don't dbzsize() it */
  181.             exact = 1;
  182.             break;
  183.         case 'M':    /* use old dbm interface + rfc822ize */
  184.             dbzint = 0;
  185.             break;
  186.         case 'U':    /* make base unopenable during init */
  187.             unopen = 1;
  188.             break;
  189.         case 'C':    /* change directories before dbmclose */
  190.             change = optarg;
  191.             break;
  192.         case 'd':    /* Debugging. */
  193.             if (dbzdebug(1) < 0)
  194.                 fail("dbz debugging not available", "");
  195.             break;
  196.         case '?':
  197.         default:
  198.             errflg++;
  199.             break;
  200.         }
  201.     if (errflg || optind >= argc || (optind+1 < argc && baseinput)) {
  202.         fprintf(stderr, "usage: %s ", progname);
  203.         fprintf(stderr, "[-a] [-x] [-c] database [file] ...\n");
  204.         exit(2);
  205.     }
  206.  
  207.     (void) dbzincore(useincore);
  208.     basename = argv[optind];
  209.     pagname = str2dup(basename, ".pag");
  210.     dirname = str2dup(basename, ".dir");
  211.     mkfiles();
  212.     optind++;
  213.  
  214.     if (baseinput)        /* implies no further arguments */
  215.         process(base, basename);
  216.     else if (optind >= argc)
  217.         process(stdin, "stdin");
  218.     else
  219.         for (; optind < argc; optind++)
  220.             dofile(argv[optind]);
  221.  
  222.     if (change != NULL)
  223.         (void) chdir(change);
  224.     if (dbmclose() < 0)
  225.         fail("dbmclose failed", "");
  226.     if (doruns)
  227.         runs(pagname);
  228.     if (sweep)
  229.         dosweep(basename, pagname);
  230.     if (printx)
  231.         printf("%ld\n", xxx);
  232. #ifdef DBZ_FINISH
  233.     DBZ_FINISH;
  234. #endif
  235.     exit(0);
  236. }
  237.  
  238. /*
  239.  - dofile - open a file and invoke process()
  240.  */
  241. void
  242. dofile(name)
  243. char *name;
  244. {
  245.     register FILE *in;
  246.  
  247.     if (STREQ(name, "-"))
  248.         process(stdin, "-");
  249.     else {
  250.         in = fopen(name, "r");
  251.         if (in == NULL)
  252.             fail("cannot open `%s'", name);
  253.         process(in, name);
  254.         (void) fclose(in);
  255.     }
  256. }
  257.  
  258. /*
  259.  - mkfiles - create empty files and open them up
  260.  */
  261. void
  262. mkfiles()
  263. {
  264.     if (op == 'b' && !dbzint) {
  265.         crfile(dirname);
  266.         crfile(pagname);
  267.     }
  268.  
  269.     base = fopen(basename, (op == 'a') ? "a" : "r");
  270.     if (base == NULL)
  271.         fail("cannot open `%s'", basename);
  272.     if (unopen)
  273.         (void) chmod(basename, 0);
  274.     if (from != NULL) {
  275.         if (dbzagain(basename, from) < 0)
  276.             fail("dbzagain(`%s'...) failed", basename);
  277.     } else if (op == 'b' && dbzint) {
  278.         if (!exact)
  279.             siz = dbzsize(siz);
  280.         if (dbzfresh(basename, siz, (int)fs, map, tag) < 0)
  281.             fail("dbzfresh(`%s'...) failed", basename);
  282.     } else if (dbminit(basename) < 0)
  283.         fail("dbminit(`%s') failed", basename);
  284.     if (unopen)
  285.         (void) chmod(basename, 0600);    /* hard to restore original */
  286. }
  287.  
  288. /*
  289.  - crfile - create a file
  290.  */
  291. void
  292. crfile(name)
  293. char *name;
  294. {
  295.     register int f;
  296.  
  297.     f = creat(name, 0666);
  298.     if (f < 0)
  299.         fail("cannot create `%s'", name);
  300.     (void) close(f);
  301. }
  302.  
  303. /*
  304.  - process - process input file
  305.  */
  306. void
  307. process(in, name)
  308. FILE *in;
  309. char *name;
  310. {
  311.     register off_t place;
  312.  
  313.     inname = name;
  314.     lineno = 0;
  315.  
  316.     for (;;) {
  317.         place = ftell(in);
  318.         if (fgets(line, buflen, in) == NULL)
  319.             return;
  320.         lineno++;
  321.         if (every > 0 && lineno%every == 0) {
  322.             fprintf(stderr, "%ld\n", lineno);
  323.             if (dbzsync() < 0)
  324.                 fail("dbzsync failed", "");
  325.         }
  326.         doline(line, place);
  327.     }
  328.     /* NOTREACHED */
  329. }
  330.  
  331. /*
  332.  - doline - process input line
  333.  */
  334. void
  335. doline(lp, inoffset)
  336. char *lp;
  337. off_t inoffset;
  338. {
  339.     register char *p;
  340.     register char pc;
  341.     datum key, value;
  342.     off_t place = inoffset;
  343.     register int shouldfind;
  344.     register int llen;
  345.     char keytext[DBZMAXKEY+1];
  346.  
  347.     p = NULL;
  348.     if (fs != '\0')
  349.         p = strchr(lp, fs);
  350.     if (p == NULL)
  351.         p = lp + strlen(lp);
  352.     if (p > lp && *(p-1) == '\n')
  353.         p--;
  354.     if (p - lp > DBZMAXKEY)
  355.         fail("key of `%.40s...' too long", lp);
  356.     pc = *p;
  357.     *p = '\0';
  358.     (void) strcpy(keytext, lp);
  359.     *p = pc;
  360.     key.dptr = (dbzint) ? keytext : rfc822ize(keytext);
  361.     key.dsize = strlen(keytext)+1;
  362.  
  363.     switch (op) {
  364.     case 'a':
  365.         place = ftell(base);
  366.         llen = strlen(lp);
  367.         if (fwrite(lp, 1, llen, base) != llen)
  368.             fail("write error in `%s'", basename);
  369.         /* FALLTHROUGH */
  370.     case 'b':
  371.         if (omitzero && p != NULL && *(p+1) == '0')
  372.             return;
  373.         if (unique) {
  374.             value = (dbzint) ? dbzfetch(key) : fetch(key);
  375.             if (value.dptr != NULL)
  376.                 fail("`%.40s...' already present", lp);
  377.         }
  378.         value.dptr = (char *)&place;
  379.         value.dsize = (int)sizeof(off_t);
  380.         if (((dbzint) ? dbzstore(key, value) : store(key, value)) < 0)
  381.             fail("store failed on `%.40s...'", lp);
  382.         break;
  383.     case 'c':
  384.         value = (dbzint) ? dbzfetch(key) : fetch(key);
  385.         shouldfind = (omitzero && p != NULL && *(p+1) == '0') ? 0 : 1;
  386.         if (!shouldfind && (value.dptr != NULL || value.dsize != 0))
  387.             fail("`%.40s...' found, shouldn't be", lp);
  388.         if (shouldfind && (value.dptr == NULL ||
  389.                     value.dsize != sizeof(off_t)))
  390.             fail("can't find `%.40s...'", lp);
  391.         if (shouldfind && !quick) {
  392.             (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
  393.             if (place != inoffset)
  394.                 fail("offset mismatch on `%.40s...'", lp);
  395.             if (fseek(base, place, SEEK_SET) == -1)
  396.                 fail("fseek failed on `%.40s...'", lp);
  397.             if (fgets(cmp, buflen, base) == NULL)
  398.                 fail("can't read line for `%.40s...'", lp);
  399.             if (!STREQ(lp, cmp))
  400.                 fail("compare failed on `%.40s...'", lp);
  401.         }
  402.         break;
  403.     case 'x':
  404.         value = (dbzint) ? dbzfetch(key) : fetch(key);
  405.         if (value.dptr != NULL && !quick) {
  406.             (void) memcpy((char *)&place, value.dptr, sizeof(off_t));
  407.             if (fseek(base, place, SEEK_SET) == -1)
  408.                 fail("fseek failed on `%.40s...'", lp);
  409.             if (fgets(cmp, buflen, base) == NULL)
  410.                 fail("can't read line for `%.40s...'", lp);
  411.             fputs(cmp, stdout);
  412.         } else if (value.dptr != NULL)
  413.             fputs(lp, stdout);
  414.         break;
  415.     case 'm':
  416.         value = (dbzint) ? dbzfetch(key) : fetch(key);
  417.         if (value.dptr == NULL) {
  418.             fputs(keytext, stdout);
  419.             putchar('\n');
  420.         }
  421.         break;
  422.     default:
  423.         fail("unknown operator -- can't happen", "");
  424.         break;
  425.     }
  426. }
  427.  
  428. /*
  429.  - runs - print run statistics
  430.  */
  431. void
  432. runs(file)
  433. char *file;
  434. {
  435.     register FILE *fd;
  436.     off_t it;
  437.     register long run;
  438.  
  439.     fd = fopen(file, "r");
  440.     if (fd == NULL)
  441.         fail("cannot reopen `%s'", file);
  442.     run = 0;
  443.     while (fread((char *)&it, sizeof(off_t), 1, fd) == 1) {
  444.         if (it != 0)
  445.             run++;
  446.         else if (run > 0) {
  447.             printf("%ld\n", run);
  448.             run = 0;
  449.         }
  450.     }
  451.     (void) fclose(fd);
  452. }
  453.  
  454. /*
  455.  - dosweep - sweep pag file checking for valid offsets
  456.  */
  457. void
  458. dosweep(fn, pn)
  459. char *fn;
  460. char *pn;
  461. {
  462.     register FILE *pf;
  463.     off_t it;
  464.     char nl;
  465.     register FILE *hf;
  466.  
  467.     hf = fopen(fn, "r");
  468.     if (hf == NULL)
  469.         fail("cannot reopen `%s'", fn);
  470.     pf = fopen(pn, "r");
  471.     if (pf == NULL)
  472.         fail("cannot reopen `%s'", pn);
  473.     while (fread((char *)&it, sizeof(off_t), 1, pf) == 1) {
  474.         it = (it & ((off_t)0x80000000)) ? (it&~((off_t)0xff000000)) : it;
  475.         if (it != 0 && it != 1) {    /* 0 empty, 1 known okay */
  476.             it--;        /* get rid of bias */
  477.             (void) fseek(hf, it-1, SEEK_SET);
  478.             nl = getc(hf);
  479.             if (nl != '\n')
  480.                 fprintf(stderr, "offset 0%lo does not point to line\n",
  481.                                 (long)it);
  482.         }
  483.     }
  484.     (void) fclose(hf);
  485.     (void) fclose(pf);
  486. }
  487.  
  488. /*
  489.  - fail - complain and die
  490.  */
  491. void
  492. fail(s1, s2)
  493. char *s1;
  494. char *s2;
  495. {
  496.     fprintf(stderr, "%s: (file `%s', line %ld) ", progname, inname, lineno);
  497.     fprintf(stderr, s1, s2);
  498.     fprintf(stderr, "\n");
  499.     exit(1);
  500. }
  501.  
  502. /*
  503.  - str2dup - concatenate strings and malloc result
  504.  */
  505. char *
  506. str2dup(s1, s2)
  507. char *s1;
  508. char *s2;
  509. {
  510.     register char *p;
  511.  
  512.     p = malloc((size_t)strlen(s1) + strlen(s2) + 1);
  513.     if (p == NULL)
  514.         fail("can't allocate space for strings", "");
  515.     (void) strcpy(p, s1);
  516.     (void) strcat(p, s2);
  517.     return(p);
  518. }
  519.